package com.bsd.xxyp.rdlock.handler;

import com.bsd.xxyp.rdlock.context.LockHolder;
import com.bsd.xxyp.rdlock.context.TemporaryVariableContext;
import com.bsd.xxyp.rdlock.entity.LockInfo;
import com.bsd.xxyp.rdlock.executor.LockExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author ：wangcheng
 * @date 2022/12/29
 **/
@Slf4j
public class DefaultLockTemplate implements LockTemplate{

    @Autowired(required = false)
    private LockHolder lockHolder;
    private Long lockTimeOut = 60 * 1000L;
    private TemporaryVariableContext variableContext;

    public DefaultLockTemplate() {
        this.variableContext = new TemporaryVariableContext();
    }

    public void setLockTimeOut(Long lockTimeOut) {
        this.lockTimeOut = lockTimeOut;
    }

    @Override
    public boolean lock(String key) {
        return lock(key,lockTimeOut,LockExecutor.Executor.DEFAULT);
    }

    @Override
    public boolean lock(String key,LockExecutor.Executor executor) {
        return lock(key,lockTimeOut,executor);
    }

    @Override
    public boolean lock(String key,Long lockTimeOut) {
        return lock(key,lockTimeOut,LockExecutor.Executor.DEFAULT);
    }

    @Override
    public boolean lock(String key,Long lockTimeOut,LockExecutor.Executor executor) {
        if (lockHolder == null) {
            log.error("获取lock执行器失败,本次加锁失效 key: {} ",key);
            return true;
        }
        LockExecutor lockExecutor = lockHolder.obtainLockExecutor(executor);

        LockInfo build = LockInfo.builder()
                .lockKey(key)
                .lockTimeout(lockTimeOut)
                .waitTime(0L)
                .build();
        variableContext.pushTempVariable(build);
        boolean lockResult = lockExecutor.tryAcquire(build);
        log.info("rdLock lockSuccess: {} ,lockKey: {} ,executor: {} ",
                lockResult,key,lockExecutor.getClass().getSimpleName());
        build.setLockSuccess(lockResult);
        return lockResult;
    }

    @Override
    public boolean unLock() {
        return unLock(LockExecutor.Executor.DEFAULT);
    }

    @Override
    public boolean unLock(LockExecutor.Executor executor) {
        if (lockHolder == null) {
            log.error("获取lock执行器失败,本次解锁失效");
            return true;
        }
        LockExecutor lockExecutor = lockHolder.obtainLockExecutor(executor);
        LockInfo lockInfo = variableContext.popTemVariable();
        boolean releaseLock = lockExecutor.releaseLock(lockInfo);
        log.info("rdLock releaseSuccess: {} ,lockKey: {} ,executor: {} ",
                releaseLock,lockInfo.getLockKey(),lockExecutor.getClass().getSimpleName());
        return releaseLock;
    }

}
